<?= hc_H1("Type Definition and Object Initialization Syntax") ?>

There's a simple syntax in <?= langname() ?> for creating
compound objects and types:

```
decl Complex := namedtuple() { 're': double, 'im': double };
decl I := Complex() { 're': 0, 'im': 1 };
decl sockaddr := dict() { 'host': "example.net", 'port': 443 };
```

In the above scenario,

- `namedtuple()` *factory function* creates such object that is
  a *type object* that creates another type object with 2 members
  named "re" and "im", this type is assigned to `Complex`,
  which is then used to create a "complex number"
  with the value of the imaginary unit;
- `dict()` factory function creates a type object that creates a
  dictionary, initializing `sockaddr` with 2 members - "host" with
  the value of "example.net" and "port" with 443.

`namedtuple`, `Complex`, and `dict` are "type objects", of which,
with `namedtuple` being sort of a meta.

A type object contains an method property named `__initset__` declared as follow:

```
method val __initset__(val key, val value);
```

**Note** The parameters of the `__initset__` method property were changed from
`ref` to `val`. For one, most usages would have keys and values as literals,
so it doesn't make sense to have references to them. Other issue is that, there
haven't been a way to signify the end of list. This is now changed to use the
setting of the existing `__proto__` property to the type object for signifying
the end-of-list. As of 2025-10-27, the `ref` argument type is removed completely.

```
objdef-start % objdefstart
: objdef-start-comma % comma
| objdef-start-nocomma % nocomma
;

objdef-start-comma % objdefstartcomma
: objdef-start-nocomma "," % genrule
;

objdef-start-nocomma % objdefstartnocomma
: postfix-expr "{" postfix-expr ":" assign-expr % base
| objdef-start-nocomma "," postfix-expr ":" assign-expr % genrule
;

object-notation % objdef
: postfix-expr "{" "}" % empty
| objdef-start "}" % some
| postfix-expr "[" "]" % emptyarray
| postfix-expr "[" expressions-list "]" % array
;
```

The `postfix-expr` MUST NOT be `inc` or `dec`. Furthermore, if `postfix-expr`
is `degenerate`, then the primary expression MUST NOT be `const`.

On encountering a `postfix-expr` that is a type object, the key-value pairs
enclosed in the braces delimited by commas are taken and the `__initset__`
method is called on them in turn. The key is the value of the postfix
expression on the left side of the colon, while the value is that of the
assignment expression on the right side of the colon. After this completes,
the `__initset__` method is invoked with `__proto__` as key and
the value of `postfix-expr` to signify the end, and then, the now value
of `postfix-expr` becomes the value of the `object-notation` expression.

**Note**: As such, the property names `__initset__` and `__proto__` are
*RESERVED* for the "Type Definition and Object Initialization Syntax".

The `array` rule is a syntax sugar that invokes `__initset__` with elements
in the `expressions-list` as value and successive integer indicies as key,
starting with 0.
